//
//  HSGradientProgressView.swift
//  HSMainViewControllerHandler
//
//  Created by haisheng huang on 2016/11/17.
//  Copyright © 2016年 haisheng huang. All rights reserved.
//

import Foundation
import UIKit
import CoreFoundation

enum GradientChangeDirection {
    case right
    case left
    case bottom
    case top
    case topLeftToBottomRight
    case topRightToBottomLeft
    case bottomLeftToTopRight
    case bottomRightToTopLeft
}

class HSGradientProgress: UIView {
    
    var deepColor: UIColor = UIColor.black
    var lightColor: UIColor = UIColor.white
    private var valueColor: UIColor?
    var value: CGFloat = 0.0 {
    
        willSet {
            
        }
        
        didSet {
            self.createGradientView()
            if self.isAnimated == true {
                self.addAnimation(duration: self.duration)
            }
        }
    }
    var direction: GradientChangeDirection = GradientChangeDirection.right  //default
    var isCornerRadius: Bool = true
    var isAnimated: Bool = false
    var gradientLayer: CAGradientLayer?
    var gradientView: UIView?
    var duration: TimeInterval = 1.5
    
    override init(frame: CGRect) {
        super.init(frame: frame)
    }
    
    required init?(coder aDecoder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
    
    convenience init(frame: CGRect, deepColor: UIColor?, lightColor: UIColor?, backgroundColor: UIColor?, value: CGFloat, isCornerRadius: Bool, direction: GradientChangeDirection?, isAnimated: Bool?, duration: TimeInterval?) {
        
        self.init(frame: frame)
        
        self.basicSetup()
        
        if deepColor != nil {
            self.deepColor = deepColor!
        }
        
        if lightColor != nil {
            self.lightColor = lightColor!
        }
        
        if backgroundColor != nil {
            self.backgroundColor = backgroundColor!
        }
        if isCornerRadius == false {
            self.isCornerRadius = false
        }
        if direction != nil {
            self.direction = direction!
        }
        
        if isAnimated == true {
            self.isAnimated = true
        }
        
        if duration != nil {
            self.duration = duration!
        }

        self.value = value

        self.createGradientView()
        
        if self.isAnimated == true {
            self.addAnimation(duration: self.duration)
        }
    }
    
    @discardableResult
    class func create(at superView: UIView, frame: CGRect, deepColor: UIColor?, lightColor: UIColor?, backgroundColor: UIColor?, value: CGFloat, isCornerRadius: Bool, direction: GradientChangeDirection?, isAnimated: Bool?, duration: TimeInterval) -> HSGradientProgress {
        
        let progress: HSGradientProgress = HSGradientProgress.init(frame: frame, deepColor: deepColor, lightColor: lightColor, backgroundColor: backgroundColor, value: value, isCornerRadius: isCornerRadius, direction: direction, isAnimated: isAnimated, duration: duration)
        superView.addSubview(progress)
        return progress
    }
    
    func basicSetup() -> Void {
//        self.layer.masksToBounds = true
        self.layer.cornerRadius = self.frame.height / 2.0
    }
    
    func createGradientLayer() -> Void {
        
        if self.value <= 1.0 && self.value >= 0.0 {
            self.getCurrentDeepColor(deepColor: self.deepColor, lightColor: self.lightColor, value: self.value)
        }
        let gradientColors: [CGColor] = [self.lightColor.cgColor, self.valueColor!.cgColor]
        
        if self.gradientLayer == nil {
            
            let gradientLayer: CAGradientLayer = CAGradientLayer()
            self.setChangeDirection(gradientLayer: gradientLayer, direction: self.direction)
            if self.isCornerRadius == true {
                gradientLayer.cornerRadius = self.frame.height / 2.0
            }
            self.gradientLayer = gradientLayer
        }
        
        self.gradientLayer!.frame = CGRect(x: 0.0, y: 0.0, width: self.frame.width * self.value, height: self.frame.height)
        self.gradientLayer!.colors = gradientColors
        
    }
    
    func createGradientView() -> Void {
        
        self.createGradientLayer()
        
        if self.gradientView == nil {
            let view: UIView = UIView()
            view.backgroundColor = UIColor.clear
            view.layer.masksToBounds = true
            view.layer.cornerRadius = self.frame.height / 2.0
            view.frame = CGRect.init(x: 0.0, y: 0.0, width: 0.0, height: self.frame.height)
            self.addSubview(view)
            view.layer.addSublayer(self.gradientLayer!)
            self.gradientView = view
        }
//        let view: UIView = UIView()
//        view.backgroundColor = UIColor.clear
//        view.layer.masksToBounds = true
////        view.layer.cornerRadius = self.frame.height / 2.0
//        view.frame = CGRect.init(x: 0.0, y: 0.0, width: 0.0, height: self.frame.height)
//        self.addSubview(view)
//        view.layer.addSublayer(self.gradientLayer!)
//        self.gradientView = view
//        self.viewAddCorner(view: gradientView!, radius: self.frame.height / 2.0, borderWidth: 0.0, backgroundColor: UIColor.clear, borderColor: UIColor.clear);
    }
    
    func getCurrentDeepColor(deepColor: UIColor, lightColor: UIColor, value: CGFloat) -> Void {
        let deepColorComponents: [CGFloat] = deepColor.cgColor.components!
        let lightColorComponents: [CGFloat] = lightColor.cgColor.components!
        var red: CGFloat = 0.0
        var green: CGFloat = 0.0
        var blue: CGFloat = 0.0
        
        if deepColorComponents[0] == 1.0 && deepColorComponents[0] == lightColorComponents[0] {
            red = 1.0
        } else if deepColorComponents[0] > lightColorComponents[0] {
            red = lightColorComponents[0] + (deepColorComponents[0] - lightColorComponents[0]) * value
        } else if deepColorComponents[0] < lightColorComponents[0] {
            red = lightColorComponents[0] - (lightColorComponents[0] - deepColorComponents[0]) * value
        }
        
        if deepColorComponents[1] == 1.0 && deepColorComponents[1] == lightColorComponents[1] {
            green = 1.0
        } else if deepColorComponents[1] > lightColorComponents[1] {
            green = lightColorComponents[1] + (deepColorComponents[1] - lightColorComponents[1]) * value
        } else if deepColorComponents[1] < lightColorComponents[1] {
            green = lightColorComponents[1] - (lightColorComponents[1] - deepColorComponents[1]) * value
        }
        
        if deepColorComponents[2] == 1.0 && deepColorComponents[2] == lightColorComponents[2] {
            blue = 1.0
        } else if deepColorComponents[2] > lightColorComponents[2] {
            blue = lightColorComponents[2] + (deepColorComponents[2] - lightColorComponents[2]) * value
        } else if deepColorComponents[2] < lightColorComponents[2] {
            blue = lightColorComponents[2] - (lightColorComponents[2] - deepColorComponents[2]) * value
        }
        
        self.valueColor = UIColor(red: red, green: green, blue: blue, alpha: 1.0)
        
    }
    
    func setChangeDirection(gradientLayer: CAGradientLayer, direction: GradientChangeDirection) -> Void {
        switch direction {
        case .right:
            gradientLayer.startPoint = CGPoint.init(x: 0.0, y: 0.5)
            gradientLayer.endPoint = CGPoint.init(x: 1.0, y: 0.5)
        case .left:
            gradientLayer.startPoint = CGPoint.init(x: 1.0, y: 0.5)
            gradientLayer.endPoint = CGPoint.init(x: 0.0, y: 0.5)
        case .bottom:
            gradientLayer.startPoint = CGPoint.init(x: 0.5, y: 0.0)
            gradientLayer.endPoint = CGPoint.init(x: 0.5, y: 1.0)
        case .top:
            gradientLayer.startPoint = CGPoint.init(x: 0.5, y: 1.0)
            gradientLayer.endPoint = CGPoint.init(x: 0.5, y: 0.0)
        case .topLeftToBottomRight:
            gradientLayer.startPoint = CGPoint.init(x: 0.0, y: 0.0)
            gradientLayer.endPoint = CGPoint.init(x: 1.0, y: 1.0)
        case .topRightToBottomLeft:
            gradientLayer.startPoint = CGPoint.init(x: 1.0, y: 0.0)
            gradientLayer.endPoint = CGPoint.init(x: 0.0, y: 1.0)
        case .bottomLeftToTopRight:
            gradientLayer.startPoint = CGPoint.init(x: 0.0, y: 1.0)
            gradientLayer.endPoint = CGPoint.init(x: 1.0, y: 0.0)
        default:
            gradientLayer.startPoint = CGPoint.init(x: 1.0, y: 1.0)
            gradientLayer.endPoint = CGPoint.init(x: 0.0, y: 0.0)
        }
    }
    
    func addAnimation(duration: TimeInterval) -> Void {
        
        UIView.animate(withDuration: duration, animations: { [unowned self] in
            
            self.gradientView?.frame.size.width = self.frame.width * self.value
        }, completion: { finish in
            
        })
    }
    
    func kt_drawRectWithRoundedCorner(_ radius: CGFloat,
                                      borderWidth: CGFloat,
                                      backgroundColor: UIColor,
                                      borderColor: UIColor) -> UIImage {
        let sizeToFit = CGSize(width: pixel(num: Double(self.bounds.size.width)), height: Double(self.bounds.size.height))
        let halfBorderWidth = CGFloat(borderWidth / 2.0)
        
        UIGraphicsBeginImageContextWithOptions(sizeToFit, false, UIScreen.main.scale)
        let context = UIGraphicsGetCurrentContext()
        
        context!.setLineWidth(borderWidth)
        context!.setStrokeColor(borderColor.cgColor)
        context!.setFillColor(backgroundColor.cgColor)
        
        let width = sizeToFit.width, height = sizeToFit.height
//        CGContextMoveToPoint(context, width - halfBorderWidth, radius + halfBorderWidth)
        context?.move(to: CGPoint(x: width - halfBorderWidth, y: radius + halfBorderWidth)) // 开始坐标右边开始
//        CGContextAddArcToPoint(context, width - halfBorderWidth, height - halfBorderWidth, width - radius - halfBorderWidth, height - halfBorderWidth, radius)
        context?.addArc(tangent1End: CGPoint(x: width - halfBorderWidth, y: height - halfBorderWidth), tangent2End: CGPoint(x: width - radius - halfBorderWidth, y: height - halfBorderWidth), radius: radius)// 右下角角度
        
//        CGContextAddArcToPoint(context, halfBorderWidth, height - halfBorderWidth, halfBorderWidth, height - radius - halfBorderWidth, radius)
        context?.addArc(tangent1End: CGPoint(x: halfBorderWidth, y: height - halfBorderWidth), tangent2End: CGPoint(x: halfBorderWidth, y: height - radius - halfBorderWidth), radius: radius)
        // 左下角角度
//        CGContextAddArcToPoint(context, halfBorderWidth, halfBorderWidth, width - halfBorderWidth, halfBorderWidth, radius)
        context?.addArc(tangent1End: CGPoint(x: halfBorderWidth, y: halfBorderWidth), tangent2End: CGPoint(x: width - halfBorderWidth , y: halfBorderWidth), radius: radius)// 左上角
//        CGContextAddArcToPoint(context, width - halfBorderWidth, halfBorderWidth, width - halfBorderWidth, radius + halfBorderWidth, radius)
        context?.addArc(tangent1End: CGPoint(x: width - halfBorderWidth, y: halfBorderWidth), tangent2End: CGPoint(x: width - halfBorderWidth, y: radius + halfBorderWidth), radius: radius)// 右上角
        
        UIGraphicsGetCurrentContext()!.drawPath(using: .fillStroke)
        let output = UIGraphicsGetImageFromCurrentImageContext()
        UIGraphicsEndImageContext()
        return output!
    }
    
    private func roundbyunit(num: Double, unit: inout Double) -> Double {
        let remain = modf(num, &unit)
        if (remain > unit / 2.0) {
            return ceilbyunit(num: num, unit: &unit)
        } else {
            return floorbyunit(num: num, unit: &unit)
        }
    }
    private func ceilbyunit(num: Double, unit: inout Double) -> Double {
        return num - modf(num, &unit) + unit
    }
    
    private func floorbyunit(num: Double, unit: inout Double) -> Double {
        return num - modf(num, &unit)
    }
    
    private func pixel(num: Double) -> Double {
        var unit: Double
        switch Int(UIScreen.main.scale) {
        case 1: unit = 1.0 / 1.0
        case 2: unit = 1.0 / 2.0
        case 3: unit = 1.0 / 3.0
        default: unit = 0.0
        }
        return roundbyunit(num: num, unit: &unit)
    }
    
    func viewAddCorner(view: UIView, radius: CGFloat,
                       borderWidth: CGFloat,
                       backgroundColor: UIColor,
                       borderColor: UIColor) -> Void {
        
        let imageView = UIImageView(image: kt_drawRectWithRoundedCorner(radius,
                                                                        borderWidth: borderWidth,
                                                                        backgroundColor: backgroundColor,
                                                                        borderColor: borderColor))
        view.insertSubview(imageView, at: 0)
    }
    
    
}




